#include "PsoInertiaUpdateMethods.h"

namespace jcrada {

    LinearDecreasingInertia::LinearDecreasingInertia( int max_iterations ) : PsoInertiaUpdateMethod( ),
    _max_iterations( max_iterations ) {

    }

    void LinearDecreasingInertia::updateInertia( PsoParticle& particle, const PsoModel& model ) {
        double inertia = 1.0;
        if (getMaxIterations() <= model.getCurrentIteration()) {
            inertia = getMinInertia();
        } else {
            inertia = (getMaxInertia() - getMinInertia());
            inertia *= (getMaxIterations() - model.getCurrentIteration());
            inertia /= getMaxIterations();
            inertia += getMinInertia();
        }
        particle.setInertia(inertia);
    }

    //NON LINEAR DECREASING

    NonLinearDecreasingInertia::NonLinearDecreasingInertia( int max_iterations ) : PsoInertiaUpdateMethod( ),
    _max_iterations( max_iterations ) {

    }

    void NonLinearDecreasingInertia::updateInertia( PsoParticle& particle, const PsoModel& model ) {
        double inertia = (model.getCurrentIteration() != 0 ? particle.getInertia() : getMaxInertia()) - getMinInertia();
        inertia *= (getMaxIterations() - model.getCurrentIteration());
        inertia /= (getMaxInertia() + getMinInertia());
        particle.setInertia(inertia);
    }

    //    void RelativeImprovementInertia::updateInertia( PsoParticle& particle, const PsoModel& model ) {
    //        double f_nbest = getFitnessForNeighborhoodBest();
    //        double f_pbest = getFitnessForPersonalBest();
    //
    //        double avg_fitness = (f_nbest + f_pbest) / 2;
    //        double mi_t = avg_fitness - getFitness();
    //        mi_t /= (avg_fitness + getFitness() + 1);
    //        inertia = (exp(mi_t) - 1) / (exp(mi_t) + 1);
    //        inertia *= (getPsoModel()->getMaxInertiaWeight() - getPsoModel()->getMinInertiaWeight());
    //        inertia += getPsoModel()->getMinInertiaWeight();
    //    }
}
